package com.twq.func.basic

/**
 * Created by tangweiqun on 2017/11/28.
 */
object FirstClassFunction {
  def main(args: Array[String]): Unit = {
    //1、function literal(函数字面量)
    //在编译的时候function literal是一个class，但是在运行时的时候是一个object(称之为function value)
    (x: Int) =>
      x + 1

      //2、既然function value是对象，那么就可以将function value赋值给一个变量
      var increase = (x: Int) => x + 1
      increase(10)

      increase = (x: Int) => x + 9999
      increase(10)

      increase = (x: Int) => {
        println("We")
        println("are")
        println("here!")
        x + 1
      }
      increase(10)

      //3、函数可以作为函数的参数进行传递
      val someNumbers = List(-11, -10, -5, 0, 5, 10)
      someNumbers.foreach((x: Int) => println(x))
      val func = (x: Int) => x > 0
      someNumbers.filter(func)

      //4、使得function literal更简洁
      //去掉参数的类型(编译器会推断出x的类型是Int)：
      someNumbers.filter((x) => x > 0)
      //去掉参数的括号：
      someNumbers.filter(x => x > 0)
      //用下划线做占位符, 前提是参数在函数体只出现了一次
      someNumbers.filter(_ > 0)

      (a: Int, b: Int) =>
        a + b
        val f = (_: Int) + (_: Int)
        f(5, 10)

        //5、partially applied functions
        //这里的下划线并不是一个参数的占位符，而是整个参数列表的占位符，这个其实就是partially applied functions
        someNumbers.foreach(println _)

        def sum(a: Int, b: Int, c: Int) = a + b + c

        sum(1, 2, 3)
        val aSum = sum _
        aSum.apply(1, 2, 3)
        aSum(1, 2, 3) //就是上面的缩写

        val bSum = sum(1, _: Int, 3)
        bSum(2)
        bSum(5)

        //6、如果函数当作参数的话，下划线都可以去掉
        someNumbers.foreach(println)
  }
}
